﻿Imports System.IO
Imports System.Xml
Imports System.Xml.Serialization
Imports Microsoft.Reporting.WinForms

Public Class DynamicAddColSample
    'https://blog.csdn.net/weixin_30394633/article/details/98573176
    '不懂请查阅

    Dim reportViewer1 As ReportViewer

    ''' <summary>
    ''' 修改RDLC文件 (为了动态生成N 列)
    ''' </summary>
    ''' <returns></returns>
    Private Function ModifyRdlc() As XmlDocument

        Dim xmlDoc = New XmlDocument()

        xmlDoc.Load(AppDomain.CurrentDomain.BaseDirectory + "FirstRdlc.rdlc")

        '添加Field节点
        Dim fileds = xmlDoc.GetElementsByTagName("Fields")

        Dim filedNode = fileds.Item(0).FirstChild.CloneNode(True)

        filedNode.Attributes("Name").Value = "GPA"

        filedNode.FirstChild.InnerText = "GPA"
        fileds.Item(0).AppendChild(filedNode)


        '添加TablixColumn

        Dim tablixColumns = xmlDoc.GetElementsByTagName("TablixColumns")
        Dim tablixColumn = tablixColumns.Item(0).FirstChild
        Dim newtablixColumn = tablixColumn.CloneNode(True)
        tablixColumns.Item(0).AppendChild(newtablixColumn)

        'TablixMember
        Dim tablixMembers = xmlDoc.GetElementsByTagName("TablixColumnHierarchy")

        Dim tablixMember = tablixMembers.Item(0).FirstChild.FirstChild
        Dim newTablixMember = tablixMember.CloneNode(True)
        tablixMembers.Item(0).FirstChild.AppendChild(newTablixMember)

        Dim tablixRows = xmlDoc.GetElementsByTagName("TablixRows")

        'TablixRows1
        Dim tablixRowsRowCells1 = tablixRows.Item(0).FirstChild.ChildNodes(1)
        Dim tablixRowCell1 = tablixRowsRowCells1.FirstChild
        Dim newtablixRowCell1 = tablixRowCell1.CloneNode(True)
        Dim textBox1 = newtablixRowCell1.FirstChild.ChildNodes(0)

        textBox1.Attributes("Name").Value = "GPA1"

        ' VB lamdba 一行写完根本不可能.
        Dim paragraphs = textBox1.ChildNodes.Cast(Of XmlNode)().Where(Function(item)
                                                                          Return item.Name = "Paragraphs"
                                                                      End Function).FirstOrDefault()

        paragraphs.FirstChild.FirstChild.FirstChild.FirstChild.InnerText = "GPA"

        Dim defaultName1 = textBox1.ChildNodes.Cast(Of XmlNode)().Where(Function(item)
                                                                            Return item.Name = "rd:DefaultName"
                                                                        End Function).FirstOrDefault().InnerText = "GPA1"

        tablixRowsRowCells1.AppendChild(newtablixRowCell1)

        'TablixRows2
        Dim tablixRowsRowCells2 = tablixRows.Item(0).ChildNodes(1).ChildNodes(1)
        Dim tablixRowCell2 = tablixRowsRowCells2.FirstChild
        Dim newtablixRowCell2 = tablixRowCell2.CloneNode(True)
        Dim textBox2 = newtablixRowCell2.FirstChild.ChildNodes(0)
        textBox2.Attributes("Name").Value = "GPA"

        Dim paragraphs2 = textBox2.ChildNodes.Cast(Of XmlNode)().Where(Function(item)
                                                                           Return item.Name = "Paragraphs"
                                                                       End Function).FirstOrDefault()

        paragraphs2.FirstChild.FirstChild.FirstChild.FirstChild.InnerText = "=Fields!GPA.Value"
        Dim defaultName2 = textBox2.ChildNodes.Cast(Of XmlNode)().Where(Function(item)
                                                                            Return item.Name = "rd:DefaultName"
                                                                        End Function
        ).FirstOrDefault().InnerText = "GPA"

        tablixRowsRowCells2.AppendChild(newtablixRowCell2)

        xmlDoc.Save(AppDomain.CurrentDomain.BaseDirectory + "FirstRdlc1.rdlc")
        Return xmlDoc

    End Function


    Private Function GetRdlcStream(xmlDoc As XmlDocument) As Stream
        Dim ms As Stream = New MemoryStream()
        Dim serializer = New XmlSerializer(xmlDoc.GetType())
        serializer.Serialize(ms, xmlDoc)
        ms.Position = 0
        Return ms
    End Function

    Private Sub ModifyXSD()
        Dim xmlDoc = New XmlDocument()
        xmlDoc.Load(AppDomain.CurrentDomain.BaseDirectory + "Students.xsd")

        Dim nodeList = xmlDoc.GetElementsByTagName("xs:sequence")
        Dim node = nodeList.Item(0).FirstChild.CloneNode(True)
        node.Attributes("name").Value = "GPA"
        node.Attributes("msprop:Generator_ColumnVarNameInTable").Value = "columnGPA"
        node.Attributes("msprop:Generator_ColumnPropNameInRow").Value = "GPA"
        node.Attributes("msprop:Generator_ColumnPropNameInTable").Value = "GPAColumn"
        node.Attributes("msprop:Generator_UserColumnName").Value = "GPA"
        nodeList.Item(0).AppendChild(node)

        xmlDoc.Save(AppDomain.CurrentDomain.BaseDirectory + "Students1.xsd")
    End Sub

    Private Sub LoadReport()
        '获取数据源
        Dim dataSource = GetDataSource()

        '修改xsd文件   '暂时不需要修改 数据库映射过来的 xsd文件
        'ModifyXSD()

        '修改rdlc文件
        Dim xmlDoc = ModifyRdlc()

        '将修改后的rdlc文档序列化到内存流中
        Dim stream = GetRdlcStream(xmlDoc)

        '加载报表定义
        reportViewer1.LocalReport.LoadReportDefinition(stream)
        'rvDemo.LocalReport.ReportPath = "FirstRdlc.rdlc"

        '添加数据源，rvDemo是页面上的ReportView控件
        reportViewer1.LocalReport.DataSources.Add(New ReportDataSource("dsStudent", dataSource))
        reportViewer1.LocalReport.Refresh()
    End Sub




    Private Function GetDataSource() As DataTable
        '伪造一个数据源
        Dim dt = New DataTable()

        dt.Columns.Add("RecId")
        dt.Columns.Add("Name")
        dt.Columns.Add("Age")
        dt.Columns.Add("Class")
        dt.Columns.Add("Scores")
        dt.Columns.Add("GPA")


        Dim dr = dt.NewRow()
        dr("RecId") = "1"
        dr("Name") = "小明"
        dr("Age") = "26"
        dr("Class") = "1年级"
        dr("Scores") = "90"
        dr("GPA") = "4.0"

        dt.Rows.Add(dr)
        Return dt
    End Function

End Class
